﻿using System;
using Mono.Collections.Generic;

namespace Mono.Cecil
{
	// Token: 0x02000097 RID: 151
	public class MetadataResolver : IMetadataResolver
	{
		// Token: 0x17000128 RID: 296
		// (get) Token: 0x0600057E RID: 1406 RVA: 0x0001E9D8 File Offset: 0x0001CBD8
		public IAssemblyResolver AssemblyResolver
		{
			get
			{
				return this.assembly_resolver;
			}
		}

		// Token: 0x0600057F RID: 1407 RVA: 0x0001E9F0 File Offset: 0x0001CBF0
		public MetadataResolver(IAssemblyResolver assemblyResolver)
		{
			bool flag = assemblyResolver == null;
			if (flag)
			{
				throw new ArgumentNullException("assemblyResolver");
			}
			this.assembly_resolver = assemblyResolver;
		}

		// Token: 0x06000580 RID: 1408 RVA: 0x0001EA20 File Offset: 0x0001CC20
		public virtual TypeDefinition Resolve(TypeReference type)
		{
			Mixin.CheckType(type);
			type = type.GetElementType();
			IMetadataScope scope = type.Scope;
			bool flag = scope == null;
			if (!flag)
			{
				switch (scope.MetadataScopeType)
				{
				case MetadataScopeType.AssemblyNameReference:
				{
					AssemblyDefinition assemblyDefinition = this.assembly_resolver.Resolve((AssemblyNameReference)scope);
					bool flag2 = assemblyDefinition == null;
					if (flag2)
					{
						return null;
					}
					return MetadataResolver.GetType(assemblyDefinition.MainModule, type);
				}
				case MetadataScopeType.ModuleReference:
				{
					bool flag3 = type.Module.Assembly == null;
					if (flag3)
					{
						return null;
					}
					Collection<ModuleDefinition> modules = type.Module.Assembly.Modules;
					ModuleReference moduleReference = (ModuleReference)scope;
					for (int i = 0; i < modules.Count; i++)
					{
						ModuleDefinition moduleDefinition = modules[i];
						bool flag4 = moduleDefinition.Name == moduleReference.Name;
						if (flag4)
						{
							return MetadataResolver.GetType(moduleDefinition, type);
						}
					}
					break;
				}
				case MetadataScopeType.ModuleDefinition:
					return MetadataResolver.GetType((ModuleDefinition)scope, type);
				}
				throw new NotSupportedException();
			}
			return null;
		}

		// Token: 0x06000581 RID: 1409 RVA: 0x0001EB48 File Offset: 0x0001CD48
		private static TypeDefinition GetType(ModuleDefinition module, TypeReference reference)
		{
			TypeDefinition typeDefinition = MetadataResolver.GetTypeDefinition(module, reference);
			bool flag = typeDefinition != null;
			TypeDefinition result;
			if (flag)
			{
				result = typeDefinition;
			}
			else
			{
				bool flag2 = !module.HasExportedTypes;
				if (flag2)
				{
					result = null;
				}
				else
				{
					Collection<ExportedType> exportedTypes = module.ExportedTypes;
					for (int i = 0; i < exportedTypes.Count; i++)
					{
						ExportedType exportedType = exportedTypes[i];
						bool flag3 = exportedType.Name != reference.Name;
						if (!flag3)
						{
							bool flag4 = exportedType.Namespace != reference.Namespace;
							if (!flag4)
							{
								return exportedType.Resolve();
							}
						}
					}
					result = null;
				}
			}
			return result;
		}

		// Token: 0x06000582 RID: 1410 RVA: 0x0001EBF0 File Offset: 0x0001CDF0
		private static TypeDefinition GetTypeDefinition(ModuleDefinition module, TypeReference type)
		{
			bool flag = !type.IsNested;
			TypeDefinition result;
			if (flag)
			{
				result = module.GetType(type.Namespace, type.Name);
			}
			else
			{
				TypeDefinition typeDefinition = type.DeclaringType.Resolve();
				bool flag2 = typeDefinition == null;
				if (flag2)
				{
					result = null;
				}
				else
				{
					result = typeDefinition.GetNestedType(type.TypeFullName());
				}
			}
			return result;
		}

		// Token: 0x06000583 RID: 1411 RVA: 0x0001EC48 File Offset: 0x0001CE48
		public virtual FieldDefinition Resolve(FieldReference field)
		{
			Mixin.CheckField(field);
			TypeDefinition typeDefinition = this.Resolve(field.DeclaringType);
			bool flag = typeDefinition == null;
			FieldDefinition result;
			if (flag)
			{
				result = null;
			}
			else
			{
				bool flag2 = !typeDefinition.HasFields;
				if (flag2)
				{
					result = null;
				}
				else
				{
					result = this.GetField(typeDefinition, field);
				}
			}
			return result;
		}

		// Token: 0x06000584 RID: 1412 RVA: 0x0001EC94 File Offset: 0x0001CE94
		private FieldDefinition GetField(TypeDefinition type, FieldReference reference)
		{
			while (type != null)
			{
				FieldDefinition field = MetadataResolver.GetField(type.Fields, reference);
				bool flag = field != null;
				FieldDefinition result;
				if (flag)
				{
					result = field;
				}
				else
				{
					bool flag2 = type.BaseType == null;
					if (!flag2)
					{
						type = this.Resolve(type.BaseType);
						continue;
					}
					result = null;
				}
				return result;
			}
			return null;
		}

		// Token: 0x06000585 RID: 1413 RVA: 0x0001ECF0 File Offset: 0x0001CEF0
		private static FieldDefinition GetField(Collection<FieldDefinition> fields, FieldReference reference)
		{
			for (int i = 0; i < fields.Count; i++)
			{
				FieldDefinition fieldDefinition = fields[i];
				bool flag = fieldDefinition.Name != reference.Name;
				if (!flag)
				{
					bool flag2 = !MetadataResolver.AreSame(fieldDefinition.FieldType, reference.FieldType);
					if (!flag2)
					{
						return fieldDefinition;
					}
				}
			}
			return null;
		}

		// Token: 0x06000586 RID: 1414 RVA: 0x0001ED5C File Offset: 0x0001CF5C
		public virtual MethodDefinition Resolve(MethodReference method)
		{
			Mixin.CheckMethod(method);
			TypeDefinition typeDefinition = this.Resolve(method.DeclaringType);
			bool flag = typeDefinition == null;
			MethodDefinition result;
			if (flag)
			{
				result = null;
			}
			else
			{
				method = method.GetElementMethod();
				bool flag2 = !typeDefinition.HasMethods;
				if (flag2)
				{
					result = null;
				}
				else
				{
					result = this.GetMethod(typeDefinition, method);
				}
			}
			return result;
		}

		// Token: 0x06000587 RID: 1415 RVA: 0x0001EDB0 File Offset: 0x0001CFB0
		private MethodDefinition GetMethod(TypeDefinition type, MethodReference reference)
		{
			while (type != null)
			{
				MethodDefinition method = MetadataResolver.GetMethod(type.Methods, reference);
				bool flag = method != null;
				MethodDefinition result;
				if (flag)
				{
					result = method;
				}
				else
				{
					bool flag2 = type.BaseType == null;
					if (!flag2)
					{
						type = this.Resolve(type.BaseType);
						continue;
					}
					result = null;
				}
				return result;
			}
			return null;
		}

		// Token: 0x06000588 RID: 1416 RVA: 0x0001EE0C File Offset: 0x0001D00C
		public static MethodDefinition GetMethod(Collection<MethodDefinition> methods, MethodReference reference)
		{
			for (int i = 0; i < methods.Count; i++)
			{
				MethodDefinition methodDefinition = methods[i];
				bool flag = methodDefinition.Name != reference.Name;
				if (!flag)
				{
					bool flag2 = methodDefinition.HasGenericParameters != reference.HasGenericParameters;
					if (!flag2)
					{
						bool flag3 = methodDefinition.HasGenericParameters && methodDefinition.GenericParameters.Count != reference.GenericParameters.Count;
						if (!flag3)
						{
							bool flag4 = !MetadataResolver.AreSame(methodDefinition.ReturnType, reference.ReturnType);
							if (!flag4)
							{
								bool flag5 = methodDefinition.HasThis != reference.HasThis;
								if (!flag5)
								{
									bool flag6 = methodDefinition.IsVarArg() != reference.IsVarArg();
									if (!flag6)
									{
										bool flag7 = methodDefinition.IsVarArg() && MetadataResolver.IsVarArgCallTo(methodDefinition, reference);
										MethodDefinition result;
										if (flag7)
										{
											result = methodDefinition;
										}
										else
										{
											bool flag8 = methodDefinition.HasParameters != reference.HasParameters;
											if (flag8)
											{
												goto IL_140;
											}
											bool flag9 = !methodDefinition.HasParameters && !reference.HasParameters;
											if (flag9)
											{
												result = methodDefinition;
											}
											else
											{
												bool flag10 = !MetadataResolver.AreSame(methodDefinition.Parameters, reference.Parameters);
												if (flag10)
												{
													goto IL_140;
												}
												result = methodDefinition;
											}
										}
										return result;
									}
								}
							}
						}
					}
				}
				IL_140:;
			}
			return null;
		}

		// Token: 0x06000589 RID: 1417 RVA: 0x0001EF78 File Offset: 0x0001D178
		private static bool AreSame(Collection<ParameterDefinition> a, Collection<ParameterDefinition> b)
		{
			int count = a.Count;
			bool flag = count != b.Count;
			bool result;
			if (flag)
			{
				result = false;
			}
			else
			{
				bool flag2 = count == 0;
				if (flag2)
				{
					result = true;
				}
				else
				{
					for (int i = 0; i < count; i++)
					{
						bool flag3 = !MetadataResolver.AreSame(a[i].ParameterType, b[i].ParameterType);
						if (flag3)
						{
							return false;
						}
					}
					result = true;
				}
			}
			return result;
		}

		// Token: 0x0600058A RID: 1418 RVA: 0x0001EFF4 File Offset: 0x0001D1F4
		private static bool IsVarArgCallTo(MethodDefinition method, MethodReference reference)
		{
			bool flag = method.Parameters.Count >= reference.Parameters.Count;
			bool result;
			if (flag)
			{
				result = false;
			}
			else
			{
				bool flag2 = reference.GetSentinelPosition() != method.Parameters.Count;
				if (flag2)
				{
					result = false;
				}
				else
				{
					for (int i = 0; i < method.Parameters.Count; i++)
					{
						bool flag3 = !MetadataResolver.AreSame(method.Parameters[i].ParameterType, reference.Parameters[i].ParameterType);
						if (flag3)
						{
							return false;
						}
					}
					result = true;
				}
			}
			return result;
		}

		// Token: 0x0600058B RID: 1419 RVA: 0x0001F098 File Offset: 0x0001D298
		private static bool AreSame(TypeSpecification a, TypeSpecification b)
		{
			bool flag = !MetadataResolver.AreSame(a.ElementType, b.ElementType);
			bool result;
			if (flag)
			{
				result = false;
			}
			else
			{
				bool isGenericInstance = a.IsGenericInstance;
				if (isGenericInstance)
				{
					result = MetadataResolver.AreSame((GenericInstanceType)a, (GenericInstanceType)b);
				}
				else
				{
					bool flag2 = a.IsRequiredModifier || a.IsOptionalModifier;
					if (flag2)
					{
						result = MetadataResolver.AreSame((IModifierType)a, (IModifierType)b);
					}
					else
					{
						bool isArray = a.IsArray;
						if (isArray)
						{
							result = MetadataResolver.AreSame((ArrayType)a, (ArrayType)b);
						}
						else
						{
							bool isFunctionPointer = a.IsFunctionPointer;
							result = (!isFunctionPointer || MetadataResolver.AreSame((FunctionPointerType)a, (FunctionPointerType)b));
						}
					}
				}
			}
			return result;
		}

		// Token: 0x0600058C RID: 1420 RVA: 0x0001F154 File Offset: 0x0001D354
		private static bool AreSame(FunctionPointerType a, FunctionPointerType b)
		{
			bool flag = a.HasThis != b.HasThis;
			bool result;
			if (flag)
			{
				result = false;
			}
			else
			{
				bool flag2 = a.CallingConvention != b.CallingConvention;
				if (flag2)
				{
					result = false;
				}
				else
				{
					bool flag3 = !MetadataResolver.AreSame(a.ReturnType, b.ReturnType);
					if (flag3)
					{
						result = false;
					}
					else
					{
						bool flag4 = a.ContainsGenericParameter != b.ContainsGenericParameter;
						if (flag4)
						{
							result = false;
						}
						else
						{
							bool flag5 = a.HasParameters != b.HasParameters;
							if (flag5)
							{
								result = false;
							}
							else
							{
								bool flag6 = !a.HasParameters;
								if (flag6)
								{
									result = true;
								}
								else
								{
									bool flag7 = !MetadataResolver.AreSame(a.Parameters, b.Parameters);
									result = !flag7;
								}
							}
						}
					}
				}
			}
			return result;
		}

		// Token: 0x0600058D RID: 1421 RVA: 0x0001F224 File Offset: 0x0001D424
		private static bool AreSame(ArrayType a, ArrayType b)
		{
			bool flag = a.Rank != b.Rank;
			return !flag;
		}

		// Token: 0x0600058E RID: 1422 RVA: 0x0001F250 File Offset: 0x0001D450
		private static bool AreSame(IModifierType a, IModifierType b)
		{
			return MetadataResolver.AreSame(a.ModifierType, b.ModifierType);
		}

		// Token: 0x0600058F RID: 1423 RVA: 0x0001F274 File Offset: 0x0001D474
		private static bool AreSame(GenericInstanceType a, GenericInstanceType b)
		{
			bool flag = a.GenericArguments.Count != b.GenericArguments.Count;
			bool result;
			if (flag)
			{
				result = false;
			}
			else
			{
				for (int i = 0; i < a.GenericArguments.Count; i++)
				{
					bool flag2 = !MetadataResolver.AreSame(a.GenericArguments[i], b.GenericArguments[i]);
					if (flag2)
					{
						return false;
					}
				}
				result = true;
			}
			return result;
		}

		// Token: 0x06000590 RID: 1424 RVA: 0x0001F2F0 File Offset: 0x0001D4F0
		private static bool AreSame(GenericParameter a, GenericParameter b)
		{
			return a.Position == b.Position;
		}

		// Token: 0x06000591 RID: 1425 RVA: 0x0001F310 File Offset: 0x0001D510
		private static bool AreSame(TypeReference a, TypeReference b)
		{
			bool flag = a == b;
			bool result;
			if (flag)
			{
				result = true;
			}
			else
			{
				bool flag2 = a == null || b == null;
				if (flag2)
				{
					result = false;
				}
				else
				{
					bool flag3 = a.etype != b.etype;
					if (flag3)
					{
						result = false;
					}
					else
					{
						bool isGenericParameter = a.IsGenericParameter;
						if (isGenericParameter)
						{
							result = MetadataResolver.AreSame((GenericParameter)a, (GenericParameter)b);
						}
						else
						{
							bool flag4 = a.IsTypeSpecification();
							if (flag4)
							{
								result = MetadataResolver.AreSame((TypeSpecification)a, (TypeSpecification)b);
							}
							else
							{
								bool flag5 = a.Name != b.Name || a.Namespace != b.Namespace;
								result = (!flag5 && MetadataResolver.AreSame(a.DeclaringType, b.DeclaringType));
							}
						}
					}
				}
			}
			return result;
		}

		// Token: 0x04000162 RID: 354
		private readonly IAssemblyResolver assembly_resolver;
	}
}
